----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:20:07 04/16/2012 
-- Design Name: 
-- Module Name:    top_level - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE, work;
use IEEE.STD_LOGIC_1164.ALL;
use work.game_support.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity top_level is
    Port ( clk : in  STD_LOGIC;
           red : out  STD_LOGIC_VECTOR (2 downto 0);
           green : out  STD_LOGIC_VECTOR (2 downto 0);
           blue : out  STD_LOGIC_VECTOR (1 downto 0);
           h_sync : out  STD_LOGIC;
           v_sync : out  STD_LOGIC;
			  voice : in std_logic;
			  button0, button1, button2, button3 : in std_logic;
			 accelerometer : in std_logic;
			
eoc			: in  STD_LOGIC;	-- end of conversion, will be sent out as oe
ADC			: in std_logic_vector(7 downto 0);
oe : out std_logic;
start			: out STD_LOGIC;  -- start signal, will be timed to be eoc
adc_clock : inout std_logic;
addrA			: out STD_LOGIC;  -- address A input, will toggle between potentiometers
ale			: out std_logic;
			  
			  normal_controller_data : in std_logic;
			  normal_controller_latch, normal_controller_clock : out std_logic;
			  
			  led : out std_logic_vector(7 downto 0);
				segments: out std_logic_vector(6 downto 0);
				sw: in std_logic_vector(3 downto 0);
				anode : out std_logic_vector(3 downto 0)
				);


end top_level;

architecture Behavioral of top_level is

	signal clk_40MHz : std_logic;
	signal clk_1KHz : std_logic := '0';
	signal clk_2MHz : std_logic := '0';
	
	signal addrA_internal : std_logic;
	
	component clock_generator is
		 generic (desiredFreq : positive range 1 to 5E6);
		 Port ( clk_50MHz : in  STD_LOGIC;
				  clk_out : out  STD_LOGIC);
	end component;
	
	component nes_controller is
		 PORT(
         clk : IN  std_logic;
         load : OUT  std_logic;
         serial_data : IN  std_logic;
			direction : out paddle_direction
        );
	end component;
	
	
	COMPONENT clock_wizard_ip
	PORT(
		CLKIN_IN : IN std_logic;          
		CLKFX_OUT : OUT std_logic
		);
	END COMPONENT;
	
	component video_logic_unit is
		Port (
			clk : in std_logic;
			red : out std_logic_vector (2 downto 0);
			green : out std_logic_vector (2 downto 0);
			blue : out std_logic_vector (1 downto 0);
			h_sync : out std_logic;
			v_sync : out std_logic;
			top_collision : in std_logic;
			bottom_collision : in std_logic;
			h_count : out std_logic_vector(10 downto 0);
			v_count : out std_logic_vector(10 downto 0);

			player1_here, player2_here, ball_here, brick_here : in std_logic
		);
	end component;

	component object_controller is
		Port (
			clk : in std_logic;
			voice : in std_logic;
			top_col : out std_logic;
			bottom_col : out std_logic;
			h_count : in std_logic_vector(10 downto 0);
			v_count : in std_logic_vector(10 downto 0);
			player1_left, player1_right, player2_left, player2_right : in std_logic;
			increment_p1, increment_p2 : out std_logic;
			sw : in std_logic_vector(3 downto 0);
			player1_here, player2_here, ball_here : out std_logic;
			brick_here : out std_logic
		);
	end component;
	
	
	component ADC_accell is
    Port ( 
		clk_in		: in  STD_LOGIC;	-- input clk, twice frequency of output clock	
		eoc			: in  STD_LOGIC;	-- end of conversion, will be sent out as oe
		clk_out		: out STD_LOGIC;  -- clock out, half of input frequency
		oe				: out std_logic;  -- output enable
		start			: out STD_LOGIC;  -- start signal, will be timed to be eoc
		addrA			: out STD_LOGIC;  -- address A input, will toggle between potentiometers
		ale			: out STD_LOGIC;	-- address latch enable, toggled high when correct address is sent	
		data_ready	: out std_logic
	 );
end component;

	component seven_seg_module is
		Port (
			clk : in std_logic;
			data : in std_logic_vector(15 downto 0);
			segments : out std_logic_vector(6 downto 0);
			anode : out std_logic_vector(3 downto 0)
		);
	end component;
	
	component score_counter is
		Port (
			clk : in std_logic;
			update_count : in std_logic;
			count : out std_logic_vector(3 downto 0));
	end component;
--	component sev_seg is
--	port (
--      clk : in std_logic;
--      inc_p1 : in std_logic;
--		inc_p2  : in std_logic;
--      segment1 : out std_logic_vector(6 downto 0);  -- 7 bit decoded output.
--		segment2 : out std_logic_vector(6 downto 0)  
--    );
--end component;


	signal h_count : std_logic_vector(10 downto 0);
	signal v_count : std_logic_vector(10 downto 0);
	
	signal adc_data_ready : std_logic;

	signal player1_here, player2_here, ball_here, brick_here : std_logic;

	signal player1_left, player1_right : std_logic;
	signal player2_left, player2_right : std_logic;
	
	signal p1_direction : paddle_direction;
	
	signal top_col_sig, bottom_col_sig : std_logic;
	
	signal current_accelerometer0_data, next_accelerometer0_data : std_logic_vector(3 downto 0);
	signal current_accelerometer1_data, next_accelerometer1_data : std_logic_vector(3 downto 0);
	
	signal inc_p1, inc_p2 : std_logic;
	signal p1_score, p2_score : std_logic_vector(3 downto 0);
	signal seven_seg_data : std_logic_vector(15 downto 0);
	
signal ADC_Sig	:  std_logic_vector(7 downto 0);
begin

	p1_score_counter : score_counter
		Port map (
			clk => clk_40MHz,
			update_count => inc_p1,
			count => p1_score
		);
		
	p2_score_counter : score_counter
		Port map (
			clk => clk_40MHz,
			update_count => inc_p2,
			count => p2_score
		);
	
	seven_seg_data <= x"0" & p1_score & x"0" & p2_score;


	my_seven_seg_module : seven_seg_module
		Port map (
			clk => clk,
			data => seven_seg_data,
			segments => segments,
			anode => anode
		);
	

		--led <= (others => '0');
		normal_controller_clock <= '0';
		normal_controller_latch <= '0';
		
--		player2_left <= button2;
--		player2_right <=button3;

		Inst_clock_wizard_ip: clock_wizard_ip PORT MAP(
		CLKIN_IN => clk,
		CLKFX_OUT => clk_40MHz
	);
	
--		my_clock_generator : clock_generator
--		generic map (desiredFreq => 1E3)
--		port map (
--			clk_50MHz => clk,
--			clk_out => clk_1KHz
--		);
		
		adc_clock_generator : clock_generator
		generic map (desiredFreq => 1E6)
		port map (
			clk_50MHz => clk,
			clk_out => clk_2Mhz
		);
		
--		my_nes_controller : nes_controller
--		port map (
--			clk => clk_1KHz,
--			load => normal_controller_latch,
--			serial_data => normal_controller_data,
--			direction => p1_direction
--		);
		
		my_vlu : video_logic_unit
		port map (
			clk => clk_40MHz,
			red => red,
			green => green,
			blue => blue,
			h_sync => h_sync,
			v_sync => v_sync,
			h_count => h_count,
			v_count => v_count,
			top_collision => top_col_sig,
			bottom_collision => bottom_col_sig,

			player1_here => player1_here,
			player2_here => player2_here,
			ball_here => ball_here,
			brick_here => brick_here
		);

		my_object_controller : object_controller
		port map (
			clk => clk_40MHz,
			player1_left => player1_left,
			player1_right => player1_right,
			player2_left => player2_left,
			player2_right => player2_right,
			voice => voice,
			increment_p1 => inc_p1, 
			increment_p2 => inc_p2,
			bottom_col => bottom_col_sig,
			top_col => top_col_sig,
			
			h_count => h_count,
			v_count => v_count,
			sw => sw,
			player1_here => player1_here,
			player2_here => player2_here,
			ball_here => ball_here,
			brick_here => brick_here
		);


inst_ADC_State : ADC_accell
Port map ( 
		clk_in	=> clk_2MHz,	
		eoc		=> eoc,	
		clk_out	=> adc_clock,	
		oe			=> oe,	
		start		=> start,	
		addrA		=> addrA_internal,	
		ale		=> ale,
		data_ready => adc_data_ready
	 );


--inst_seg : sev_seg 
--port map (
--      clk => clk,
--		inc_p1 => inc_p1,
--		inc_p2 => inc_p2,
--      segment1 => segment1,
--		segment2 => segment2
--		-- 7 bit decoded output.
--    );



LED(3 downto 0) <= current_accelerometer1_data;
LED(7 downto 4) <= current_accelerometer0_data;

process(clk_2MHz)
begin
	if rising_edge(clk_2MHz) then
		current_accelerometer0_data <= next_accelerometer0_data;
		current_accelerometer1_data <= next_accelerometer1_data;
	end if;
end process;

process(current_accelerometer0_data, current_accelerometer1_data, adc_data_ready, addrA_internal)
begin
	case adc_data_ready is
		when '1' =>
			case addrA_internal is
				when '0' =>
					next_accelerometer0_data <= ADC(3 downto 0);
					next_accelerometer1_data <= current_accelerometer1_data;
				when others =>
					next_accelerometer0_data <= current_accelerometer0_data;
					next_accelerometer1_data <= ADC(3 downto 0);
			end case;
			
		when others =>
			next_accelerometer0_data <= current_accelerometer0_data;
			next_accelerometer1_data <= current_accelerometer1_data;
	end case;
	
end process;



	--next_accelerometer0_data <= ADC(3 downto 0) when adc_data_ready <= '1' and addrA_internal = '0' else current_accelerometer0_data;
	--next_accelerometer1_data <= ADC(3 downto 0) when adc_data_ready <= '1' and addrA_internal = '1' else current_accelerometer1_data;
	player1_right <= '1' when current_accelerometer0_data = "0110" else '0';
	player1_left <= '1' when current_accelerometer0_data = "0101" else '0';
	player2_left <= '1' when current_accelerometer1_data = "0010" else '0';
	player2_right <= '1' when current_accelerometer1_data = "0110" else '0';

	addrA <= addrA_internal;

end Behavioral;

